﻿using System;
using System.Collections.Generic;
using System.Linq;
using Wise.TimeWarrior.DTO;
using Wise.TimeWarrior.Helpers;
using Wise.TimeWarrior.Interfaces;
using Wise.TimeWarrior.OSFunctionalitiesProxy;

namespace Wise.TimeWarrior.Impl
{
    /// <summary>
    /// <see cref="IWorkingDayKeeper"/>
    /// </summary>
    public class WorkingDayKeeperService : IWorkingDayKeeper
    {
        /// <summary>
        /// <see cref="IWorkingDayKeeper.DateTimeProvider"/>
        /// </summary>
        public IDateTimeProvider DateTimeProvider { set; private get; }
        /// <summary>
        /// <see cref="IWorkingDayKeeper.DataStoreService"/>
        /// </summary>
        public IDataStore DataStoreService { set; private get; }
        /// <summary>
        /// <see cref="IWorkingDayKeeper.SystemUsageService"/>
        /// </summary>
        public ISystemUsage SystemUsageService { set; private get; }

        private WorkingDayDto currentWorkingDay;
        private DateTime actuallDate;

        public void AddImmediate()
        {
            SystemUsageService.DoSnapshoot();
        }

        /// <summary>
        /// <see cref="IWorkingDayKeeper.GetWorkingDay"/>
        /// </summary>
        public WorkingDayDto GetWorkingDay()
        {
            if (currentWorkingDay == null)
            {
                actuallDate = DateTimeProvider.Now();
                currentWorkingDay = new WorkingDayDto() { CreationDateTime = actuallDate };
            }
            else if (actuallDate.Day != DateTimeProvider.Now().Day)
            {
                actuallDate = DateTimeProvider.Now();
                currentWorkingDay = new WorkingDayDto() { CreationDateTime = actuallDate };
            }

            //first try to obtain data for 
            List<UserEventDto> eventsForCurentDay = DataStoreService.GetData(new DateTime(actuallDate.Year, actuallDate.Month, actuallDate.Day), null);

            if (currentWorkingDay.FirstAction == null)
            {

                if (eventsForCurentDay != null && eventsForCurentDay.Count > 0)
                {
                    currentWorkingDay.FirstAction = eventsForCurentDay.OrderBy(p => p.EventDate).First(p => p.EventDate.Day == actuallDate.Day);
                }
                else
                {
                    currentWorkingDay.FirstAction = SystemUsageService.Events.OrderBy(p => p.EventDate).First(p => p.EventDate.Day == actuallDate.Day);
                }
            }


            UserEventDto lastEvent = SystemUsageService.Events.OrderBy(p => p.EventDate).LastOrDefault(p => p.EventDate.Day == actuallDate.Day);

            if (lastEvent != null)
            {
                currentWorkingDay.LastAction = lastEvent;
            }
            else
            {
                currentWorkingDay.LastAction = eventsForCurentDay.OrderBy(p => p.EventDate).Last(p => p.EventDate.Day == actuallDate.Day);
            }



            return currentWorkingDay;
        }


        /// <summary>
        /// <see cref="IWorkingDayKeeper.GetDataInformationForSpecifiedDates"/>
        /// </summary>
        public List<WorkingDayDto> GetDataInformationForSpecifiedDates(DateTime from, DateTime? to = null)
        {
            List<WorkingDayDto> workingDays = new List<WorkingDayDto>();

            List<UserEventDto> eventDtos = DataStoreService.GetData(from, to);
            var groupedEvents = eventDtos.GroupBy(p => DateTimeHelper.LowerToDayStart(p.EventDate));

            foreach (IGrouping<DateTime, UserEventDto> l in groupedEvents)
            {
                WorkingDayDto workingDay = new WorkingDayDto() { CreationDateTime = l.Key };
                UserEventDto firstEvent = l.OrderBy(p => p.EventDate).First(p => p.EventDate.Day == l.Key.Day);
                UserEventDto lastEvent = l.OrderBy(p => p.EventDate).LastOrDefault(p => p.EventDate.Day == l.Key.Day);
                workingDay.FirstAction = firstEvent;
                workingDay.LastAction = lastEvent;
                workingDays.Add(workingDay);
            }

            Console.WriteLine(eventDtos.Count);

            return workingDays;
        }

    }
}
